package darlingbastard.stacks;

import org.apache.taglibs.standard.tag.common.core.OutSupport;
import org.apache.taglibs.standard.tag.common.core.NullAttributeException;
import org.apache.taglibs.standard.tag.el.core.ExpressionUtil;

import javax.servlet.jsp.JspException;
import java.io.IOException;

/**
 * Created by bishope
 * Date: Mar 11, 2006
 */
public class OutTag extends OutSupport {

    //*********************************************************************
    // 'Private' state (implementation details)

    private String var;
    private String value_;			// stores EL-based property
    private String default_;			// stores EL-based property
    private String escapeXml_;			// stores EL-based property


    //*********************************************************************
    // Constructor

    public OutTag() {
        super();
        init();
    }


    //*********************************************************************
    // Tag logic

    private boolean needBody;

    // evaluates expression and chains to parent
    public int doStartTag() throws JspException {
        needBody = false;
        // evaluate any expressions we were passed, once per invocation
        evaluateExpressions();

        // chain to the parent implementation
//	return super.doStartTag();
//        needBody = false;			// reset state related to 'default'
        this.bodyContent = null;  // clean-up body (just in case container is pooling tag handlers)

        try {
            // print value if available; otherwise, try 'default'
            if (value != null && !needBody) {
                out(pageContext, escapeXml, String.valueOf(value));
                return SKIP_BODY;
            } else {
                // if we don't have a 'default' attribute, just go to the body
                if (def == null) {
                    needBody = true;
                    return EVAL_BODY_BUFFERED;
                }

                // if we do have 'default', print it
                if (def != null) {
                    // good 'default'
                    out(pageContext, escapeXml, def);
                }
                return SKIP_BODY;
            }
        } catch (IOException ex) {
            throw new JspException(ex.toString(), ex);
        }
    }

    public int doEndTag() throws JspException {
        try {
            if (!needBody)
                return EVAL_PAGE;		// nothing more to do

            // trim and print out the body
//            if (bodyContent != null && bodyContent.getString() != null)
                out(pageContext, escapeXml, processSuperRef(bodyContent.getString().trim()));
            return EVAL_PAGE;
        } catch (IOException ex) {
            throw new JspException(ex.toString(), ex);
        }
    }

    private String processSuperRef(String bodyContent) {
        if (bodyContent == null) return String.valueOf(value);
        if (value == null) return bodyContent;
        System.out.println("");
        System.out.println("");
        System.out.println("OutTag.processSuperRef");
        System.out.println("bodyContent = " + bodyContent);
        System.out.println("value = " + value);
        String toMatch = "_s_super." + var + "_s_";
        return String.valueOf(value).replaceAll(toMatch, bodyContent);
    }

    // Releases any resources we may have (or inherit)
    public void release() {
        super.release();
        init();
    }


    //*********************************************************************
    // Accessor methods

    public void setValue(String value_) {
        this.value_ = value_;
    }

    public void setDefault(String default_) {
        this.default_ = default_;
    }

    public void setEscapeXml(String escapeXml_) {
        this.escapeXml_ = escapeXml_;
    }


    //*********************************************************************
    // Private (utility) methods

    // (re)initializes state (during release() or construction)
    private void init() {
        // null implies "no expression"
	value_ = default_ = escapeXml_ = null;
    }

    /* Evaluates expressions as necessary */
    private void evaluateExpressions() throws JspException {

        if (var.startsWith("super."))
            value_ = "_s_" + var + "_s_";
        else
            value_ = "${" + var + "}";

        try {
            value = ExpressionUtil.evalNotNull(
                    "out", "value", value_, Object.class, this, pageContext);
        } catch (NullAttributeException ex) {
            // explicitly allow 'null' for value
            value = null;
        }

        if (value != null) {
            String toMatch = "_s_super." + var + "_s_";
            if (value.toString().indexOf(toMatch) >= 0) {
                needBody = true;
            }
        }

        try {
            def = (String) ExpressionUtil.evalNotNull(
                    "out", "default", default_, String.class, this, pageContext);
        } catch (NullAttributeException ex) {
            // explicitly allow 'null' for def
            def = null;
        }
        escapeXml = false;
        Boolean escape = ((Boolean) ExpressionUtil.evalNotNull(
                "out", "escapeXml", escapeXml_, Boolean.class, this, pageContext));
        if (escape != null)
            escapeXml = escape.booleanValue();
    }

    public void setVar(String var) {
        this.var = var;
    }


}
